package cc.jinglupeng.wechat.api;

import java.io.File;
import java.util.List;
import java.util.Map;

import cc.jinglupeng.wechat.bean.group.Group;
import cc.jinglupeng.wechat.bean.media.Media;
import cc.jinglupeng.wechat.bean.media.MediaId;
import cc.jinglupeng.wechat.bean.menu.Menu;
import cc.jinglupeng.wechat.bean.message.MessageType;
import cc.jinglupeng.wechat.bean.message.mass.Article;
import cc.jinglupeng.wechat.bean.message.mass.MassStatus;
import cc.jinglupeng.wechat.bean.message.mass.MsgId;
import cc.jinglupeng.wechat.bean.message.send.CustomMessage;
import cc.jinglupeng.wechat.bean.oauth.OAuthAccessToken;
import cc.jinglupeng.wechat.bean.oauth.OAuthUser;
import cc.jinglupeng.wechat.bean.qrcoe.Qrcode;
import cc.jinglupeng.wechat.bean.user.User;
import cc.jinglupeng.wechat.bean.user.Users;
import cc.jinglupeng.wechat.consts.MediaType;

/**
 * 
 * 为所有API提供一个统一的入口，并且提供一些简化的方法
 * 
 * @author jinglupeng.cc
 */
public class WeChatAPI {
	private String appId;

	private WeChatAPI(String appId) {
		this.appId = appId;
	}

	public static WeChatAPI getAPI(String appId) {
		return new WeChatAPI(appId);
	}

	// BaseAPI

	/**
	 * 获取AccessToken，优先从缓存获取。获取AccessToken接口每天可获取2000次，每次有效期7200秒，
	 * 获取新的AccessToken后旧的立刻失效。
	 * 所以需要对AccessToken进行缓存，如果多个系统需要同时调用微信接口，则必须对AccessToken进行统一管理
	 * 
	 * @return
	 */
	public String getAccessToken() {
		return BaseAPI.getAccessToken(appId);
	}

	/**
	 * 上传多媒体文件到微信服务器
	 * 
	 * @param file
	 *            -文件
	 * @param type
	 *            -媒体文件类型，分别有图片（image）、语音（voice）、视频（video）和缩略图（thumb）
	 * @return
	 */
	public MediaId uploadMedia(File file, MediaType type) {
		MediaId mediaId = BaseAPI.uploadMedia(appId, file, type);
		if (mediaId == null || !mediaId.isSuccess()) {
			return null;
		}
		return mediaId;
	}

	/**
	 * 从微信服务器下载多媒体文件，该方法将文件数据缓存到内存中不做进一步处理，因此当从附件对象中读取数据结束后应该迅速将附件对象置空。
	 * 
	 * @param mediaId
	 *            -媒体文件ID
	 * @return
	 */
	public Media downMedia(String mediaId) {
		Media media = BaseAPI.downMedia(appId, mediaId);
		if (media == null || !media.isSuccess()) {
			return null;
		}
		return media;
	}

	/**
	 * 用于和微信公众平台对接，验证消息是否来自微信公众平台
	 * 
	 * @param token
	 * @param signature
	 *            -微信加密签名，signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
	 * @param timestamp
	 *            -时间戳
	 * @param nonce
	 *            -随机数
	 * @return
	 */
	public final boolean checkSignature(String token, String signature,
			String timestamp, String nonce) {
		return BaseAPI.checkSignature(token, signature, timestamp, nonce);
	}

	/**
	 * 创建分组
	 * 
	 * @param name
	 *            -分组名字（30个字符以内）
	 * @return
	 */
	public Group createGroup(String name) {
		return GroupAPI.createGroup(appId, name);
	}

	/**
	 * 查询所有分组
	 * 
	 * @return
	 */
	public List<Group> getGroups() {
		return GroupAPI.getGroups(appId);
	}

	/**
	 * 查询用户所在分组
	 * 
	 * @param openId
	 *            -用户的OpenID
	 * @return
	 */
	public String getUserGroupId(String openId) {
		return GroupAPI.getUserGroupId(appId, openId);
	}

	/**
	 * 修改分组名
	 * 
	 * @param group
	 *            -分组信息
	 * @return
	 */
	public boolean updateGroup(Group group) {
		return GroupAPI.updateGroup(appId, group);
	}

	/**
	 * 移动用户分组
	 * 
	 * @param openId
	 *            -用户唯一标识符
	 * @param groupId
	 *            -分组id
	 * @return
	 */
	public boolean moveMemberGroup(String openId, String groupId) {
		return GroupAPI.moveMemberGroup(appId, openId, groupId);
	}

	// Menu API

	/**
	 * 自定义菜单查询接口
	 * 
	 * @return
	 */
	public Menu getMenu() {
		return MenuAPI.getMenu(appId);
	}

	/**
	 * 删除菜单
	 * 
	 * @return
	 */
	public Boolean deleteMenu() {
		return MenuAPI.deleteMenu(appId);
	}

	/**
	 * 自定义菜单创建
	 * 
	 * @param menu
	 *            -JSON形式的菜单
	 * @return
	 */
	public Boolean createMenu(String menu) {
		return MenuAPI.createMenu(appId, menu);
	}

	// Message API
	/**
	 * 发送客服消息
	 * 
	 * @param message
	 *            -JSON形式的客服消息
	 * @return
	 */
	public boolean sendCustomMessage(String message) {
		return MessageAPI.sendCustomMessage(appId, message).isSuccess();
	}

	/**
	 * 发送客服消息
	 * 
	 * @param message
	 *            -客服消息
	 * @param openId
	 *            -普通用户openid
	 * @return
	 */
	public boolean sendCustomMessage(CustomMessage message, String openId) {
		return MessageAPI.sendCustomMessage(appId, message, openId).isSuccess();
	}

	/**
	 * 高级群发消息
	 * 
	 * @param type
	 *            -消息类型
	 * @param mediaId
	 *            -文本类型为文本内容，其它类型为消息Id
	 * @return
	 */
	public MsgId sendMassMessage(MessageType type, String mediaId) {
		MsgId msgId = MessageAPI.sendMassMessage(appId, type, mediaId);
		if (msgId == null || !msgId.isSuccess()) {
			return null;
		}
		return msgId;
	}

	/**
	 * 按openId列表进行高级群发
	 * 
	 * @param type
	 *            -消息类型
	 * @param mediaId
	 *            -文本类型为文本内容，其它类型为消息Id
	 * @param openIds
	 *            -消息的接收者，一串OpenID列表，OpenID最少1个，最多10000个
	 * @return
	 */
	public MsgId sendMassMessage(MessageType type, String mediaId,
			List<String> openIds) {
		MsgId msgId = MessageAPI.sendMassMessage(appId, type, mediaId, openIds);
		if (msgId == null || !msgId.isSuccess()) {
			return null;
		}
		return msgId;
	}

	/**
	 * 根据分组过滤进行高级群发
	 * 
	 * @param type
	 *            -消息类型
	 * @param mediaId
	 *            -文本类型为文本内容，其它类型为消息Id
	 * @param groupId
	 *            -群发到的分组的group_id
	 * @return
	 */
	public MsgId sendMassMessage(MessageType type, String mediaId,
			String groupId) {
		MsgId msgId = MessageAPI.sendMassMessage(appId, type, mediaId, groupId);
		if (msgId == null || !msgId.isSuccess()) {
			return null;
		}
		return msgId;
	}

	/**
	 * 上传图文消息素材
	 * 
	 * @param articles
	 *            -图文消息，一个图文消息支持1到10条图文
	 * @return
	 */
	public MediaId uploadNews(List<Article> articles) {
		MediaId mediaId = MessageAPI.uploadNews(appId, articles);
		if (mediaId == null || !mediaId.isSuccess()) {
			return null;
		}
		return mediaId;
	}

	/**
	 * 上传视频
	 * 
	 * @param mediaId
	 *            -通过基础支持中的上传下载多媒体文件来得到
	 * @param title
	 *            -消息的标题
	 * @param description
	 *            -消息的描述
	 * @return
	 */
	public MediaId uploadVideo(String mediaId, String title, String description) {
		MediaId media_Id = MessageAPI.uploadVideo(appId, mediaId, title,
				description);
		if (media_Id == null || !media_Id.isSuccess()) {
			return null;
		}
		return media_Id;
	}

	/**
	 * 预览接口
	 * 
	 * @param type
	 *            -消息类型
	 * @param mediaId
	 *            -文本类型为文本内容，其它类型为消息Id
	 * @param openId
	 *            -接收消息用户对应该公众号的openid
	 */
	public MsgId previewMessage(MessageType type, String mediaId, String openId) {
		MsgId msgId = MessageAPI.preview(appId, type, mediaId, openId);
		if (msgId == null || !msgId.isSuccess()) {
			return null;
		}
		return msgId;
	}

	/**
	 * 删除群发
	 * 
	 * @param msgId
	 *            -发送出去的消息ID
	 * @return
	 */
	public boolean deleteMessage(String msgId) {
		return MessageAPI.delete(appId, msgId).isSuccess();
	}

	/**
	 * 查询群发消息发送状态
	 * 
	 * @param msgId
	 *            -发送出去的消息ID
	 * @return
	 */
	public boolean queryMessageStatus(String msgId) {
		MassStatus status = MessageAPI.queryStatus(appId, msgId);
		if (status == null || !status.isSuccess()) {
			return false;
		}
		return status.getMsg_status().equals(MassStatus.SEND_SUCCESS);
	}

	// OAuth API
	/**
	 * 获取OAuth2授权API，不弹出授权页面，直接跳转，只能获取用户openid
	 * 
	 * @param uri
	 *            -授权后重定向的回调链接地址
	 * @return
	 */
	public String generateOAuth2BaseUrl(String uri) {
		return OAuth2API.generateOAuth2BaseUrl(appId, uri);
	}

	/**
	 * 获取OAuth2授权API，弹出授权页面，可通过openid拿到昵称、性别、所在地。并且，即使在未关注的情况下，只要用户授权，也能获取其信息
	 * 
	 * @param uri
	 *            -授权后重定向的回调链接地址
	 * @return
	 */
	public String generateOAuth2UserInfoUrl(String uri) {
		return OAuth2API.generateOAuth2UserInfoUrl(appId, uri);
	}

	/**
	 * 通过code换取网页授权access_token
	 * 
	 * @param code
	 *            -code
	 * @return
	 */
	public OAuthAccessToken getOAuthAccessToken(String code) {
		OAuthAccessToken accessToken = OAuth2API.getAccessToken(appId, code);
		if (accessToken == null || !accessToken.isSuccess()) {
			return null;
		}
		return accessToken;
	}

	/**
	 * 通过Code换取OpenId
	 * 
	 * @param code
	 *            -code
	 * @return
	 */
	public String getOpenIdByCode(String code) {
		OAuthAccessToken accessToken = OAuth2API.getAccessToken(appId, code);
		if (accessToken == null || !accessToken.isSuccess()) {
			return null;
		}
		return accessToken.getOpenid();
	}

	/**
	 * 刷新网页授权access_token
	 * 
	 * @param refreshToken
	 *            -refreshToken
	 * @return
	 */
	public OAuthAccessToken refreshAccessToken(String refreshToken) {
		OAuthAccessToken accessToken = OAuth2API.refreshAccessToken(appId,
				refreshToken);
		if (accessToken == null || !accessToken.isSuccess()) {
			return null;
		}
		return accessToken;
	}

	/**
	 * 通过网页授权AccessToken拉取用户信息
	 * 
	 * @param accessToken
	 */
	public OAuthUser getOAuthUserInfo(String accessToken, String openId) {
		OAuthUser user = OAuth2API.getUserInfo(accessToken, openId);
		if (user == null || !user.isSuccess()) {
			return null;
		}
		return user;
	}

	// QrCoe API
	/**
	 * 创建二维码ticket，当seconds为0的或者空时，创建永久有效二维码
	 * 
	 * @param sceneId
	 *            -场景值ID，临时二维码时为32位非0整型，永久二维码时最大值为100000（目前参数只支持1--100000）
	 * @param seconds
	 *            -该二维码有效时间，以秒为单位。 最大不超过1800。当为0或者空的时候，则创建永久有效二维码
	 * @return
	 */
	public Qrcode createQrcode(Integer sceneId, Integer seconds) {
		Qrcode qrcode = QrcodeAPI.createQrcode(appId, sceneId, seconds);
		if (qrcode == null || !qrcode.isSuccess()) {
			return null;
		}
		return qrcode;
	}

	/**
	 * 通过ticket换取二维码
	 * 
	 * @param ticket
	 *            -二维码ticket
	 * @return
	 */
	public String getQrCodeURL(String ticket) {
		return QrcodeAPI.getQrCodeURL(ticket);
	}

	// URL API
	/**
	 * 长链接转短链接
	 * 
	 * @param url
	 *            -长链接
	 * @return
	 */
	public String toShortUrl(String longUrl) {
		return URLAPI.toShort(appId, longUrl);
	}

	// User API
	/**
	 * 获取用户基本信息
	 * 
	 * @param openId
	 *            -普通用户的标识，对当前公众号唯一
	 * @return
	 */
	public User getUserInfo(String openId) {
		User user = UserAPI.getUserInfo(appId, openId);
		if (user == null || !user.isSuccess()) {
			return null;
		}
		return user;
	}

	/**
	 * 设置备注名
	 * 
	 * @param openId
	 *            -用户标识
	 * @param remark
	 *            -新的备注名，长度必须小于30字符
	 * @return
	 */
	public boolean updateUserRemark(String openId, String remark) {
		return UserAPI.updateUserRemark(appId, openId, remark);
	}

	/**
	 * 获取关注者列表
	 * 
	 * @param nextOpenId
	 *            -拉取列表的后一个用户的OPENID
	 * @return
	 */
	public Users getUserList(String nextOpenId) {
		Users users = UserAPI.getUserList(appId, nextOpenId);
		if (users == null || !users.isSuccess()) {
			return null;
		}
		return users;
	}

	// JS SDK
	/**
	 * 获取 JS SDK Ticket
	 * 
	 * @return
	 */
	public String getJSAPITicket() {
		return JSAPI.getJSAPITicket(appId);
	}

	/**
	 * 签名URL
	 * 
	 * @param url
	 *            需要被签名的URL
	 * @return
	 */
	public Map<String, String> getJSAPIConfig(String url) {
		return JSAPI.getJSAPIConfig(appId, url);
	}

}
